package com.smallkingson.ylib.net.http;

import android.annotation.TargetApi;
import android.content.Context;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Handler;
import android.text.TextUtils;
import android.util.Log;

import com.smallkingson.ylib.core.Yr;
import com.smallkingson.ylib.net.http.bean.Request;
import com.smallkingson.ylib.net.http.bean.Response;
import com.smallkingson.ylib.net.http.exception.NotConnectException;

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Executor;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

public final class YHttps {

    private static Context context;

    public static final int REFRESH = 0X26;

    public static final int LOADMORE = 0X27;

    private static final int CPU_COUNT = Runtime.getRuntime()
            .availableProcessors();
    private static final int CORE_POOL_SIZE = CPU_COUNT + 1;
    private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1;
    private static final int KEEP_ALIVE = 1;
    private static Handler sHandler;

    private static YHttpHandler sYHttpHandler;

    private static final ThreadFactory sThreadFactory = new ThreadFactory() {
        private final AtomicInteger mCount = new AtomicInteger(1);

        public Thread newThread(Runnable r) {
            return new Thread(r, "YHttp #" + mCount.getAndIncrement());
        }
    };
    private static final BlockingQueue<Runnable> sPoolWorkQueue = new LinkedBlockingQueue<Runnable>(
            128);
    public static final Executor THREAD_POOL_EXECUTOR = new ThreadPoolExecutor(
            CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE, TimeUnit.SECONDS,
            sPoolWorkQueue, sThreadFactory);

    public static void init(Context context, YHttpHandler httpHandler) {
        YHttps.context = context.getApplicationContext();
        sHandler = new Handler();
        setHttpHandler(httpHandler);
    }
    public static void post(final Request request) {
        get(request.setMethod(Request.Method.POST));
    }
    public static void get(final Request request) {
        get(request, null, 3);
    }

    public static void get(final Request request,
                           final ResponseHandler responseHandler) {
        get(request, null, 3);
    }

    @TargetApi(Build.VERSION_CODES.HONEYCOMB)
    public static void get(final Request request,
                           final ResponseHandler responseHandler, int stack) {

        checkInit();
        final String logTag = Yr.createLogTag(stack);
        // 访问数据库看看数据库有没有这个request对应的response 如果有 ，查看是否过期 如果过期
        // 则网络请求，如果没有则直接返回
        if (TextUtils.isEmpty(request.getUrl())) {
            Log.i(logTag, "参数非法 ： request url ==null -->" + request);
            return;
        }

        final String info = createInfo(request);

        new AsyncTask<Object, Void, Void>() {
            @Override
            protected Void doInBackground(Object... params) {

                try {
                    final Response response = YHttpCacher.getInstance(context).getCache(request);

                    if (response != null) {

                        sHandler.post(new Runnable() {

                            @Override
                            public void run() {

                                try {
                                    request.listener.onGetSuccess(
                                            request, response);
                                } catch (Exception e) {
                                    Log.e(logTag, e.toString());
                                }
                            }
                        });
                    }
                    if (response == null || request.isRequestNet()) {

                        if (!YConnects.isConnected(context)) {

                            throw new NotConnectException();
                        }
                        HttpCallback listener = new HttpCallback() {

                            @Override
                            public void onSuccess(String response) {
                                if (responseHandler != null) {
                                    response = responseHandler
                                            .handler(response);
                                }
                                final Response r = new Response();
                                r.setAliveSecond(request.getAliveSecond());
                                r.setCacheKey(request.getCacheKey());
                                r.setOther("");
                                r.setResult(response);
                                r.setTime(System.currentTimeMillis());
                                r.setUrl(request.getUrl());
                                r.from = From.URL;
                                sHandler.post(new Runnable() {

                                    @Override
                                    public void run() {
                                        try {
                                            boolean requestCache = request.listener
                                                    .onGetSuccess(
                                                            request, r);
                                            if (requestCache) {
                                                // 只有返回对象为json时才缓存
                                                if (request.getCacheKey() != null
//                                        && (r.jsonArray != null || r.jsonObject != null)
                                                        ) {
                                                    YHttpCacher.getInstance(context).cache(r);
                                                }
                                            }
                                        } catch (Exception e) {
                                            request.listener
                                                    .onGetError(e,
                                                            request);
                                        }
                                    }
                                });

                            }

                            @Override
                            public void onError(final Exception e) {
                                sHandler.post(new Runnable() {

                                    @Override
                                    public void run() {
                                        request.listener.onGetError(
                                                e, request);
                                    }
                                });
                            }
                        };
                        if (request.getMethod() == Request.Method.GET) {

                            Log.i(logTag, "发起GET请求:---from : URL-----" + info);
                            sYHttpHandler.get(request, listener);
                        } else {
                            Log.i(logTag, "发起POST请求:---from : URL-----" + info
                                    + "   post参数：" + request.getParams());
                            sYHttpHandler.post(request, listener);
                        }
                    }
                } catch (final Exception e) {
                    sHandler.post(new Runnable() {

                        @Override
                        public void run() {

                            request.listener.onGetError(e, request);
                        }
                    });
                }
                return null;
            }

        }.executeOnExecutor(THREAD_POOL_EXECUTOR, request, responseHandler);

    }

    public static String createInfo(final Request request) {
        return "未加密 ：" + request.getCacheKey() + " 加密后 ：" + request.getUrl();
    }

    public static void setHttpHandler(YHttpHandler httpHandler) {

        sYHttpHandler = httpHandler;
    }


    public static interface ResponseHandler {

        String handler(String response);
    }

    public static void clearCache() {

        YHttpCacher.getInstance(context).clear();
    }

    private static void checkInit() {
        if (context == null) {
            throw new IllegalArgumentException(
                    "YHttps no call init(Context) before use");
        }
    }

    public static void clearCache(String like) {
        YHttpCacher.getInstance(context).clear(like);
    }

    public static interface YHttpListener {

        /**
         * @param request
         * @param response
         * @return 是否缓存 true 缓存
         * @throws Exception
         */
        boolean onGetSuccess(Request request, Response response)
                throws Exception;

        void onGetError(Exception e, Request request);
    }

    public static interface HttpCallback {

        void onSuccess(String response);

        void onError(Exception e);
    }

    public static enum From {

        URL, MEMORY, DISK
    }

    public static interface YHttpHandler {

        public void get(Request request, HttpCallback listener);

        public void post(Request request, HttpCallback listener);
    }
}
